/* 用于实现物流追踪系统中的电量检测功能
 *1 采用循环切换检测引脚的方式实现，防止报错
 * */
#include "adc.h"

int adc_data[3] = {0, 0, 0};
rt_thread_t adc_thread = RT_NULL;

cyhal_adc_t adc;
cyhal_adc_channel_t adc_channel;
cy_rslt_t result;

// 定义要测试的引脚
const cyhal_gpio_t adc_pins[] = {
    P10_3,  // 引脚10.3  检测有没有充电
    P10_4,  // 引脚10.4  检测电池1
    P10_5   // 引脚10.5  检测电池2
};

// ADC通道检测线程入口函数
static void adc_thread_entry(void *parameter)
{
    const int num_pins = sizeof(adc_pins) / sizeof(adc_pins[0]);

    // 初始化ADC
    result = cyhal_adc_init(&adc, adc_pins[0], NULL);

    if (result != CY_RSLT_SUCCESS) {
        rt_kprintf("ERROR: Failed to initialize ADC! Error code: 0x%08X\n", (unsigned int)result);
        if (result == CYHAL_ADC_RSLT_BAD_ARGUMENT) {
            rt_kprintf("  Reason: Invalid argument (check pin compatibility)\n");
        } else if (result == CYHAL_ADC_RSLT_FAILED_CLOCK) {
            rt_kprintf("  Reason: Failed to initialize ADC clock\n");
        } else if (result == CYHAL_ADC_RSLT_FAILED_INIT) {
            rt_kprintf("  Reason: Failed to initialize ADC hardware\n");
        } else if (result == CYHAL_ADC_RSLT_NO_CHANNELS) {
            rt_kprintf("  Reason: No available ADC channels\n");
        }
        return;
    }

    rt_kprintf("ADC initialized successfully.\n");

    // 配置通道设置
    cyhal_adc_channel_config_t channel_config = {
        .enabled = true,
        .enable_averaging = false,
        .min_acquisition_ns = 1000
    };

    // 线程主循环
    while (1) {
        // 循环遍历每个引脚
        for (int i = 0; i < num_pins; i++) {
            result = cyhal_adc_channel_init_diff(
                &adc_channel,
                &adc,
                adc_pins[i],
                CYHAL_ADC_VNEG,
                &channel_config
            );

            if (result != CY_RSLT_SUCCESS) {
                rt_kprintf("ERROR: Failed to initialize channel on P%d.%d! Error code: 0x%08X\n",
                          (int)(adc_pins[i] >> 4), (int)(adc_pins[i] & 0xF),
                          (unsigned int)result);
                continue;
            }

            uint32_t sum = 0;
            const int samples = 5;
            for (int s = 0; s < samples; s++) {
                uint16_t adc_value = cyhal_adc_read_u16(&adc_channel);
                sum += adc_value;
                rt_thread_mdelay(10);
            }
            uint16_t avg_value = sum / samples;
            float voltage = (float)avg_value * 3.3f / 65535.0f;
            uint32_t voltage_mv = (uint32_t)(voltage * 1000); // 转换为毫伏
            adc_data[i] = voltage_mv / 1000;
            // 输出修正后的格式
            /*rt_kprintf("P%d.%d:ADC value:(%d.%03d V)\n",
                    (int)(adc_pins[i] >> 4), (int)(adc_pins[i] & 0xF),
                    voltage_mv / 1000,
                    voltage_mv % 1000);*/
            // 释放通道资源
            cyhal_adc_channel_free(&adc_channel);
        }

        // 线程休眠，等待下一次扫描
        rt_thread_mdelay(ADC_SCAN_INTERVAL_MS);
    }

    // 正常情况下不会执行到这里，线程应该持续运行
    cyhal_adc_free(&adc);
}

// 创建并启动ADC线程（可重复调用）
int adc_start_thread(void)
{
    if (adc_thread != RT_NULL) {
        rt_kprintf("ADC thread is already running!\n");
        return 0;
    }

    adc_thread = rt_thread_create("adc_thread",
                                  adc_thread_entry,
                                  RT_NULL,
                                  ADC_THREAD_STACK_SIZE,
                                  ADC_THREAD_PRIORITY,
                                  20);

    if (adc_thread != RT_NULL) {
        rt_thread_startup(adc_thread);
        rt_kprintf("ADC thread started successfully.\n");
        return 0;
    } else {
        rt_kprintf("Failed to create ADC thread!\n");
        return -1;
    }
}

// 停止ADC线程
static void adc_stop(int argc, char **argv)
{
    if (adc_thread != RT_NULL) {
        rt_kprintf("Stopping ADC thread...\n");
        // 释放通道资源
        cyhal_adc_channel_free(&adc_channel);
        cyhal_adc_free(&adc);

        rt_thread_delete(adc_thread);
        adc_thread = RT_NULL;
        rt_kprintf("ADC thread stopped.\n");
    } else {
        rt_kprintf("ADC thread is not running.\n");
    }
}
MSH_CMD_EXPORT(adc_stop, Stop ADC thread);

// 启动ADC线程
INIT_APP_EXPORT(adc_start_thread);
